﻿using System;
using System.Collections.Generic;
using System.Text;

public class GameEngine
{
    private const char k_QuitChar = 'q';
    private const int k_MinColumn = 1;
    private ViewService m_GameView = null;
    private BoardService m_BoardService = null;
    private PlayersService m_PlayerService = null;
    private eGameMoveStatus m_CurrentGameStatus = eGameMoveStatus.Continue;
    private bool m_EndOfGame = false;

    public enum eGameMoveStatus
    {
        PlayerWin = 0,
        BoardIsFull,
        ColumnIsFull,
        Quit,
        Continue
    }

    public GameEngine()
    {
        m_GameView = new ViewService();
    }

    public void NewGame()
    {
        m_GameView.GameUserMenuSetup();
        m_BoardService = new BoardService(m_GameView.BoardViewRowSize, m_GameView.BoardViewColSize);
        m_PlayerService = new PlayersService(m_GameView.GameMode);
        m_GameView.PrintBoard(m_BoardService.BoardMatrix);

        while (m_EndOfGame == false)
        {
            for (int CurrentPlayerIndex = 0; CurrentPlayerIndex < m_PlayerService.NumOfPlayers && m_EndOfGame == false; CurrentPlayerIndex++)
            {
                managePlayerMove(CurrentPlayerIndex);

                switch (m_CurrentGameStatus)
                {
                    case eGameMoveStatus.Continue:
                        {
                            m_GameView.PrintBoard(m_BoardService.BoardMatrix);
                            break;
                        }

                    case eGameMoveStatus.PlayerWin:
                        {
                            m_PlayerService.UpdateWinnerScore(CurrentPlayerIndex);
                            m_GameView.Winner(CurrentPlayerIndex, m_PlayerService.FirstPlayerScore, m_PlayerService.SecondPlayerScore);
                            anotherGameSetup();
                            CurrentPlayerIndex = 1;
                            break;
                        }

                    case eGameMoveStatus.ColumnIsFull:
                        {
                            CurrentPlayerIndex--;
                            m_GameView.ErrorHandler(ViewService.eErrorMessage.ColumnIsFull);
                            break;
                        }

                    case eGameMoveStatus.BoardIsFull:
                        {
                            m_GameView.ErrorHandler(ViewService.eErrorMessage.BoardIsFull);
                            m_GameView.Draw(m_PlayerService.FirstPlayerScore, m_PlayerService.SecondPlayerScore);
                            m_GameView.AnotherGameMenu(ref m_EndOfGame);
                            anotherGameSetup();
                            CurrentPlayerIndex = 1;
                            break;
                        }

                    case eGameMoveStatus.Quit:
                        {
                            m_EndOfGame = true;
                            break;
                        }
                }
            }
        }

        m_GameView.EndGame();
    }

    private void anotherGameSetup()
    {
        m_GameView.AnotherGameMenu(ref m_EndOfGame);

        if (m_EndOfGame.Equals(false))
        {
            m_BoardService.DiscsCounter = 0;
            m_BoardService.MakeEmptyBoard();
            m_GameView.PrintBoard(m_BoardService.BoardMatrix);
        }
    }

    private void managePlayerMove(int i_CurrentPlayerIndex)
    {
        if (m_BoardService.DiscsCounter.Equals(m_BoardService.MaxDiscsInBoard))
        {
            m_CurrentGameStatus = eGameMoveStatus.BoardIsFull;
        }
        else
        {
            char CurrentPlayerMoveChar = getCurrentPlayerMove(i_CurrentPlayerIndex);

            if (CurrentPlayerMoveChar.Equals(k_QuitChar))
            {
                m_CurrentGameStatus = eGameMoveStatus.Quit;
            }
            else
            {
                m_CurrentGameStatus = m_BoardService.AddDisc(CurrentPlayerMoveChar, i_CurrentPlayerIndex);
            }
        }
    }

    private char getCurrentPlayerMove(int i_CurrentPlayerIndex)
    {
        char result;

        Player CurrentPlayer = m_PlayerService.GetPlayerByIndex(i_CurrentPlayerIndex);

        if (CurrentPlayer.GetType.Equals(Player.ePlayerType.User))
        {
            result = m_GameView.PlayRound();
        }
        else
        {
            result = CurrentPlayer.PlayRound(m_BoardService.BoardMatrixColSize);
        }

        return result;
    }
}
